﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using EntityBinder.Interface;

namespace EntityBinder
{
	public static class MemberAccessFactory
	{
		/// <summary>
		/// Binding flags to find members in the type object.
		/// </summary>
		internal const System.Reflection.BindingFlags SEARCH_FLAGS =
			System.Reflection.BindingFlags.Instance |
			System.Reflection.BindingFlags.NonPublic |
			System.Reflection.BindingFlags.Public |
			System.Reflection.BindingFlags.FlattenHierarchy;

		public static IMemberAccess FromType(Type _type, string _memberName)
		{
			FieldInfo field = _type.GetField(_memberName, SEARCH_FLAGS);
			if(field != null)
			{
				return new Internal.Field(_memberName, _type);
			}
			PropertyInfo property = _type.GetProperty(_memberName, SEARCH_FLAGS);
			if(property != null)
			{
				return new Internal.Property(_memberName, _type);
			}

			throw new EntityBinderException("MemberAccessFactory", "FromType", "Can not find member " + _memberName + " in type " + _type);
		}

		public static IMemberAccess FromType<T>(string _memberName)
		{
			return FromType(typeof(T), _memberName);
		}

		public static IMemberAccess FromMember(MemberInfo _info)
		{
			FieldInfo field = _info as FieldInfo;
			if(field != null)
			{
				return FromField(field);
			}
			PropertyInfo property = _info as PropertyInfo;
			if(property != null)
			{
				return FromProperty(property);
			}
			throw new EntityBinderException("MemberAccessFactory", "FromMember", "Can not create IMemberAccess from info of type " + _info.GetType());
		}

		public static IMemberAccess FromField(FieldInfo _info)
		{
			if(_info == null)
			{
				throw new EntityBinderException("MemberAccessFactory", "FromField", "_info parameter is set to null");
			}

			return new Internal.Field(_info.Name, _info.DeclaringType);
		}

		public static IMemberAccess FromProperty(PropertyInfo _info)
		{
			if (_info == null)
			{
				throw new EntityBinderException("MemberAccessFactory", "FromProperty", "_info parameter is set to null");
			}

			return new Internal.Property(_info.Name, _info.DeclaringType);
		}
	}
}
